#include "core/common_types.h"
#include "core/comdefs.h"
#include "qb_modules_unix.h"
#include "../include/qb_base.h"
#include "qbmessage/include/message_kernel.h"
#include "qbnet/include/network_service.h"
#include <dlfcn.h>
#include <assert.h>
#include <string>

#define MAXBUFSIZE 1024


namespace qb
{
    QbModules::QbModules()
    {
		m_hAppUIDll = NULL;
    }
    
    QbModules::~QbModules()
    {
        
    }
    
    int32_t QbModules::LoadResource(const char* exepath)
    {
		if (m_hAppUIDll)
		{
			return 0;
		}

		std::string strDllPath;
		if (exepath)
		{
			strDllPath.append(exepath);
		}

#if defined(CCORE_LINUX)
        strDllPath.append("/libguiframe.so");
#elif defined(CCORE_MAC)
		strDllPath.append("/libguiframe.dylib");
#endif

		m_hAppUIDll = dlopen(strDllPath.c_str(), RTLD_LAZY);
		if (!m_hAppUIDll)
		{
			return -1;
		}

        return 0;
    }
    
    int32_t QbModules::UnloadResource()
    {
		if (m_hAppUIDll)
		{
			dlclose(m_hAppUIDll);
			m_hAppUIDll = NULL;
		}

        return 0;
    }
    
    int32_t QbModules::QueryInterface(REFCLSID rclsid,REFIID riid,void** ppv)
    {
		Coms::iterator it_clsid = m_modules.find(rclsid);
		if (it_clsid != m_modules.end())
		{
			ComObjs::iterator it_riid = it_clsid->second.objs.find(riid);
			if (it_riid != it_clsid->second.objs.end())
			{
				if (((IUnknown*)it_riid->second.ppv)->QueryInterface(riid,(void **)&*ppv) >= 0)
				{
					return 0;
				}
				assert(0);
				return -1;
			}
			else
			{
				if (CreateInstance(rclsid,riid,ppv) == 0)
				{
					ComObjItem item;
					item.riid = riid;
					item.ppv = *ppv;

					it_clsid->second.objs[riid] = item;
					return 0;
				}
				assert(0);
				return -1;
			}
		}
		else
		{
			if (CreateInstance(rclsid,riid,ppv) == 0)
			{
				ComObjItem item;
				item.riid = riid;
				item.ppv = *ppv;
				((IUnknown*)item.ppv)->AddRef();

				ComItem cls_item;
				cls_item.clsid = rclsid;
				cls_item.objs[riid] = item;
				m_modules[rclsid] = cls_item;
				return 0;
			}
		}

		assert(0);
		return -1;
	}

	int32_t QbModules::CreateInstance(REFCLSID rclsid,REFIID riid,void** ppv)
	{
		if (rclsid == CLSID_NetworkService)
		{
			return NetworkService_CreateObject(rclsid, riid, ppv);
		}
		else if (rclsid == CLSID_MessageKernel)
		{
			return MessageKernel_CreateObject(rclsid, riid, ppv);
		}
		else if (rclsid == CLSID_UIQB)
		{
			if (!m_hAppUIDll)
			{
				return -1;
			}

			AppUICreateObject func = (AppUICreateObject)dlsym(m_hAppUIDll, "AppUI_CreateObject");
			if (func)
			{
				return func(rclsid, riid, ppv);
			}

			return -1;
		}
		else
		{
			assert(0);
			return -1;
		}
	}
}

